package com.ae.base.block;

import com.ae.base.ModConfig;
import com.ae.base.ModConstant;
import com.ae.base.cap.SingleItemStackHandler;
import com.ae.base.register.BlockRegister;
import com.ae.base.register.TileRegister;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class PlacedItemTile extends TileEntity {
    public SingleItemStackHandler handler;
    private int color = 0xffffff;
    private String id = ModConstant.ITEM_PLACED;
    private final LazyOptional<IItemHandler> lazyOptional = LazyOptional.of(() -> handler);

    public PlacedItemTile() {
        this(ItemStack.EMPTY, ModConfig.MAX_COUNT.get());
    }

    public PlacedItemTile(ItemStack stack, int count) {
        super(TileRegister.PLACED_ITEM_TILE.get());
        handler = new SingleItemStackHandler(stack, count, (savedStack, maxCount) -> {
            BlockPos pos = getBlockPos();
            BlockState state = level.getBlockState(getBlockPos());

            if (!level.isClientSide) {
                level.sendBlockUpdated(pos, state, state, 1);
            }

            //更新BlockState到客户端
            int i = Math.floorDiv(savedStack.getCount() * 64, maxCount);
            Integer value = state.getValue(PlacedItem.COUNT);
            if (value != i) {
                BlockState state1 = state.setValue(PlacedItem.COUNT, i);
                level.setBlockAndUpdate(pos, state1);
            }

            //当存储的物品全部取出则移除方块
            if (savedStack.isEmpty()) {
                level.setBlock(pos, Blocks.AIR.defaultBlockState(), 1);
                level.removeBlockEntity(pos);
            }
        });
    }

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        return cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ? lazyOptional.cast() : super.getCapability(cap, side);
    }

    @Override
    public CompoundNBT save(CompoundNBT compoundNBT) {
        CompoundNBT nbt = super.save(compoundNBT);
        nbt.put("Inventory", handler.serializeNBT());
        nbt.putInt("Color", color);
        nbt.putString("ShapeId", id);
        return nbt;
    }

    @Override
    public void load(BlockState state, CompoundNBT compoundNBT) {
        super.load(state, compoundNBT);
        handler.deserializeNBT(compoundNBT.getCompound("Inventory"));
        color = compoundNBT.getInt("Color");
        id = compoundNBT.getString("ShapeId");
    }

    @Override
    public void handleUpdateTag(BlockState state, CompoundNBT tag) {
        super.handleUpdateTag(state, tag);
        load(state, tag);
    }

    @Override
    public CompoundNBT getUpdateTag() {
        return save(new CompoundNBT());
    }

    @Override
    public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
        load(level.getBlockState(pkt.getPos()), pkt.getTag());
    }

    @Nullable
    @Override
    public SUpdateTileEntityPacket getUpdatePacket() {
        return new SUpdateTileEntityPacket(getBlockPos(), 1, save(new CompoundNBT()));
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public void dropAll(World world, BlockPos pos, PlacedItemTile tile) {
        ItemStack stack = tile.handler.getStackInSlot();
        int maxSize = stack.getMaxStackSize();
        int count = stack.getCount();
        int i1 = Math.floorDiv(count, maxSize);
        //修复当物品最大堆叠数小于64时掉落物会以超出上限的堆叠产生
        //TODO 待测试
        if (i1 <= 0) {
            InventoryHelper.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), stack);
        } else {
            for (int i = 0; i < i1; i++) {
                if (i < i1 - 1) {
                    InventoryHelper.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(stack.getItem(), maxSize));
                } else {
                    InventoryHelper.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(stack.getItem(), count - maxSize * i));
                }
            }
        }

        world.updateNeighbourForOutputSignal(pos, BlockRegister.PLACED_ITEM.get());
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
